package cn.iotab.iotkit.transport.api.access.handler.impl;

import cn.iotab.iotkit.transport.api.access.handler.DeviceSessionHandler;
import cn.iotab.iotkit.transport.api.access.handler.session.InMemorySessionStorage;
import cn.iotab.iotkit.transport.api.access.handler.session.Session;
import cn.iotab.iotkit.transport.api.access.handler.session.SessionStorage;
import cn.iotab.iotkit.transport.api.common.message.msg.up.SessionEvent;
import cn.iotab.iotkit.transport.api.common.message.msg.up.SessionInfo;
import cn.iotab.iotkit.transport.api.common.message.msg.up.SessionReportInfo;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

@Slf4j
public class DefaultDeviceSessionManager implements DeviceSessionHandler {

    // 默认1分钟
    public static final Long CONF_DEFAULT_SESSION_TIMEOUT = TimeUnit.MINUTES.toMillis(10);

    private final SessionStorage sessionStorage;


    public DefaultDeviceSessionManager(long sessionTimeout) {
        this.sessionStorage = new InMemorySessionStorage(sessionTimeout);
    }

    public DefaultDeviceSessionManager() {
        this(CONF_DEFAULT_SESSION_TIMEOUT);
    }

    private Session registerSession(SessionInfo sessionInfo) {
        Session session = Session.create(sessionInfo);
        sessionStorage.saveSession(session);
        return session;
    }


    private synchronized void closeSession(SessionInfo sessionInfo) {
        closeSession(sessionInfo.getSessionId());
    }

    public synchronized void closeSession(String sessionId) {
        sessionStorage.removeSession(sessionId);
    }

    public Session getSessionByDevice(String productKey, String deviceId) {
        return sessionStorage.getByDevice(productKey, deviceId);
    }

    @Override
    public void onDeviceSessionStateChange(SessionInfo sessionInfo, SessionEvent msg) {
        switch (msg) {
            case OPEN:
                registerSession(sessionInfo);
                break;
            case CLOSED:
                closeSession(sessionInfo);
                break;
            default:
                throw new IllegalStateException("unknown SessionEvent: " + msg);
        }
    }


    @Override
    public void onDeviceSessionReport(SessionInfo sessionInfo, SessionReportInfo msg) {
        String sessionId = sessionInfo.getSessionId();
        Session session = sessionStorage.getBySessionId(sessionId);
        if (session == null) {
            log.info("device session {} not exist on session report, register session", sessionInfo);
            registerSession(sessionInfo);
            session = sessionStorage.getBySessionId(sessionId);
        }
        //
        session.updateActiveTime(msg.getLastActivityTime());
        session.setSubscribedMessageTopic(msg.isSubscribedMessageTopic());
        session.setSubscribedReplyTopic(msg.isSubscribedReplyTopic());
        sessionStorage.saveSession(session);
    }
}
